/**
 * Created by Administrator on 2017/1/15.
 */

var config = require('./config');

var MJ = require('../MJ/MJ');
var MJRoom = require('../MJ/room').MJRoom;

var Const = require('./const');
var SubCode = require('../subCode');

exports.JLMJRoom = MJRoom.extend({
    _turns: 0,                  // 总圈数
    _curTurns: 0,              // 当前圈数
    _piaoStatus: 0,           // 飘状态
    _randPos: null,           // 调庄随机数，东南西北位置随机重新分配一下

    _curGangNewCard: 0,      // 当前玩家杠新牌

    init: function(rid, creator, msg) {
        this._super(rid, creator, msg);

        this._turns = msg.turns;
        this._curTurns = 1;

        this._piaoStatus = Const.PiaoStatus.NONE;

        this._randPos = {};
        var allPos = [];
        for (var i = 1, m = this.getMaxPlayer(); i <= m; ++i) {
            allPos.push(i);
        }
        for (var i = 1, m = this.getMaxPlayer(); i <= m; ++i) {
            var idx = Ext.rand(allPos.length);
            this._randPos[i] = allPos[idx];
            allPos.splice(idx, 1);
        }

        this._curGangNewCard = 0;
    },

    checkInit: function() {
        return this._super();
    },

    /******************************************************************
     * 重载的接口
     ******************************************************************/

    allocateIndex: function (uid) {
        var newIndex = 0;

        var order = 0;
        for (var i = 1, m = this.getMaxPlayer(); i <= m; ++i) {
            var iPos = 0;
            ExObject.eachKeyNum(this._randPos, function(pos, r) {
                if (r == i) {
                    iPos = pos;
                }
            });

            if (iPos && !this._players[iPos]) {
                newIndex = iPos; break;
            }
        }

        return newIndex;
    },

    getRoomConfig: function() {
        var cfg = this._super();
        cfg.destroyWaitTime = 120;
        cfg.respDestroyIgnoreOffline = false;
        return cfg;
    },

    isFinalRound: function() {
        return this._curTurns > this._turns;
    },

    getInfo: function() {
        var info = this._super();

        info.turns = this._turns;
        info.curTurns = this._curTurns;
        info.randPos = this._randPos;
        return info;
    },

    getRoundInfo: function() {
        var info = this._super();
        info.curTurns = this._curTurns;
        info.randPos = this._randPos;
        return info;
    },

    getReconnectInfo: function(rePlayer) {
        var info = this._super(rePlayer);

        info.turns = this._turns;
        info.curTurns = this._curTurns;
        info.piaoStatus = this._piaoStatus;
        info.randPos = this._randPos;
        return info;
    },

    onBeforeStartNewRound: function() {
        this._super();
        this._piaoStatus = Const.PiaoStatus.NONE;
        this._curGangNewCard = 0;
    },

    onAfterStartNewRound: function() {
        this._super();

        if (!this.getOption("PIAO")) {
            this.preStartPlay();
        }
    },

    isYPDXEnabled: function() {
        return this.getOption("YPDX");
    },

    preStartPlay: function() {
        this.initPlayersHandCards(this.getDealerIndex());
        this.startPlay();
    },

    startPlay: function() {
        var dealer = this.getDealerIndex();

        if (this.getOption("TING")) {
            this.enumPlayers(function(eIndex, ePlayer) {
                if (eIndex != dealer) {
                    var tings = ePlayer.checkTing();
                    if (tings.length == 1) {
                        this._hangupTask.addTingTask(eIndex, tings);
                    }
                    ePlayer.setTingCards(tings);
                }
            }.bind(this));
            logger.debug("room=%d sendHangupTask in=JLMJ.startPlay", this.rid());
            this._sendHangupTask(this._startPlay);
        } else {
            this._startPlay();
        }
    },

    _startPlay: function() {
        this._changeCurPlay(this.getDealerIndex());
        this._doCheckNewCardHangupTask();
    },

    onBeforePlayCard: function(player, msg, card) {
        var code = this._super(player, msg, card);
        if (code) {
            return code;
        }

        if (this.getOption("PIAO") && this._piaoStatus != Const.PiaoStatus.FINISHED) {
            return SubCode.PIAO_STATUS_ERROR;
        }

        if (player.isBaoTing() && card != player.getLastCard()) { //天听不能换牌
            return SubCode.MJ_IS_BAOTING;
        }
    },

    checkCurPlayHangupTask: function() {
        var player = this.getCurPlayer();
        if (!player.isBaoTing()) {
            var gangArray = player.checkGang();
            if (gangArray.length > 0) {
                this._hangupTask.addGangTask(player.getIndex(), gangArray);
            }
        }
    },

    checkNewCardHangupTask: function() {
        var player = this.getCurPlayer();

        var huIndexs = [];
        var huPattern = player.checkHu();
        if (huPattern != Const.Pattern.NONE) {
            var rules = [];
            if (this.getCurGang() && this._curGangNewCard) {
                rules.push(Const.ScoreRule.GSH);
            }

            var card = player.getLastCard() || player.getInitLastCard();
            this._hangupTask.addHuTask(player.getIndex(), card, player.getIndex(), huPattern, rules);
            huIndexs.push(player.getIndex());
        }

        var gangArray = player.checkGang();
        if (gangArray.length > 0 && player.isBaoTing()) {
            var newGangArray = [];
            var nowIsMenQing = player.nowIsMenQing();
            for (var i = 0; i < gangArray.length; ++i) {
                if (nowIsMenQing && !player.isMenQingGang(gangArray[i])) {
                    break;
                }

                if (!player.checkTingChangeIfGang(gangArray[i])) {
                    newGangArray.push(gangArray[i]);
                }
            }
            gangArray = newGangArray;
        }

        if (gangArray.length > 0) {
            this._hangupTask.addGangTask(player.getIndex(), gangArray);
        }

        huIndexs.forEach(function(eIndex) {
            var ePlayer = this.getPlayerByIndex(eIndex);
            if (ePlayer && ePlayer.isBaoTing()) {
                this._hangupTask.submitTask(eIndex, MJ.Task.HU);
            }
        }.bind(this));
    },

    checkPlayCardHangupTask: function(card) {
        var player = this.getCurPlayer();

        if (this.getOption("TING") && !player.isBaoTing()) {
            var tings = player.checkTing();
            if (tings.length == 1) {
                this._hangupTask.addTingTask(player.getIndex(), tings);
                player.setTingCards(tings);
            }
        }

        this._checkPlayCardHangupTask(card);
    },

    _checkPlayCardHangupTask: function(card) {
        var curPlay = this.getCurPlay();
        var nextIndex = this.getNextIndex(curPlay);

        var curPlayer = this.getCurPlayer();
        if (!curPlayer.getLastCard() || curPlayer.getLastCard() != card) { // 不是打的上次摸的牌，则重新检查听牌
            var tings = curPlayer.checkTing();
            curPlayer.setTingCards(tings);
        }

        var huIndexs = [];
        this.enumPlayers(function(eIndex, ePlayer) {
            if (eIndex != curPlay && !ePlayer.isRoundHu()) {
                if (!ePlayer.isPassHu() && ePlayer.getBaoTingPassHuTimes() < 1) {
                    var huPattern = ePlayer.checkHuWithCard(card);
                    if (huPattern != Const.Pattern.NONE) {
                        var rules = [];
                        //if (this.getCurGang() > 0) {
                        //    var gangInfo = curPlayer.getLastGang();
                        //    if (gangInfo && this.checkGangNewCard(gangInfo)) {
                        //        rules.push(Const.ScoreRule.GSP);
                        //    }
                        //}
                        if (this._curGangNewCard) {
                            rules.push(Const.ScoreRule.GSP);
                        }

                        this._hangupTask.addHuTask(ePlayer.getIndex(), card, curPlay, huPattern, rules);
                        huIndexs.push(eIndex);
                    }
                }

                if (!ePlayer.isBaoTing()) {
                    if (ePlayer.checkPengWithCard(card)) {
                        this._hangupTask.addPengTask(eIndex, card, curPlay);
                    }
                }

                if (ePlayer.checkGangWithCard(card)) {
                    var gangTask = {card: card, from: curPlay, gang: MJ.Gang.DIAN};
                    if (ePlayer.isBaoTing()) {
                        if (ePlayer.nowIsMenQing() || ePlayer.checkTingChangeIfGang(gangTask)) {
                            gangTask = null;
                        }
                    }

                    if (gangTask) {
                        this._hangupTask.addGangTask(eIndex, [gangTask]);
                    }
                }

                if (!ePlayer.isBaoTing()) {
                    if (eIndex == nextIndex) { // 下家可以吃牌
                        var maxCards = ePlayer.checkChiWithCard(card);
                        if (maxCards) {
                            this._hangupTask.addChiTask(eIndex, card, curPlay, maxCards);
                        }
                    }
                }
            }
        }.bind(this));

        huIndexs.forEach(function(eIndex) {
            var ePlayer = this.getPlayerByIndex(eIndex);
            if (ePlayer && ePlayer.isBaoTing()) {
                this._hangupTask.submitTask(eIndex, MJ.Task.HU);
            }
        }.bind(this));
    },

    checkGangHangupTask: function(playerIndex, gangInfo) {
        var card = gangInfo.card;
        if (gangInfo.type) {
            card = gangInfo.buCard;
        }

        var enablePeng = (gangInfo.type && gangInfo.buCard) ? true : false;

        var huIndexs = [];
        this.enumPlayers(function(eIndex, ePlayer) {
            if (eIndex != playerIndex && !ePlayer.isRoundHu() && !ePlayer.isPassHu() && ePlayer.getBaoTingPassHuTimes() < 1) {
                var huPattern = ePlayer.checkHuWithCard(card);
                if (huPattern != Const.Pattern.NONE) { // 抢杠
                    var rules = [];
                    rules.push(Const.ScoreRule.QG);
                    if (this._curGangNewCard) {
                        rules.push(Const.ScoreRule.GSP);
                    }
                    this._hangupTask.addHuTask(eIndex, card, playerIndex, huPattern, rules);
                    huIndexs.push(eIndex);
                }

                if (enablePeng && !ePlayer.isBaoTing()) {
                    if (ePlayer.checkPengWithCard(card)) {
                        this._hangupTask.addPengTask(eIndex, card, playerIndex);
                    }
                }
            }
        }.bind(this));
    },

    checkGangTaskQG: function(task, gangInfo) {
        if (gangInfo.type) {
            return gangInfo.buCard ? true : false;
        } else {
            return gangInfo.gang == MJ.Gang.BA;
        }
    },

    checkGangNewCard: function(gangInfo) {
        if (gangInfo.type) {
            if (gangInfo.buCard) {
                return true;
            }
            if (gangInfo.type == Const.SpecGang.XI || gangInfo.type == Const.SpecGang.YD || gangInfo.type == Const.SpecGang.JD) {
                return false;
            }
        }

        return true;
    },

    onAfterPlayCard: function(player, card, playInfo) {
        this._super(player, card, playInfo);

        if (!playInfo.existTask && player.getPlayCardCount() >= 20 && player.getPlayCards().length >= 20) {
            this.settlementCurRound(1000);
        }
    },

    onAfterChangeCurPlay: function(oldCurPlay, newCard) {
        this._super(oldCurPlay, newCard);

        if (oldCurPlay != this.getCurPlay()) {
            this._curGangNewCard = 0;
        }
    },

    onAfterGangTask: function(player, card, gangTask, gangInfo) {
        this._super(player, card, gangTask, gangInfo);

        if (!this.checkGangTaskQG(gangTask, gangInfo)) {
            if (this.checkGangNewCard(gangInfo)) {
                this._curGangNewCard = 1;
            }
        }
    },

    onHangupTaskDone: function(source, taskId) {
        this._super(source, taskId);

        if (source.task == MJ.Task.PLAY) {
            var player = this.getPlayerByIndex(source.playerIndex);
            if (player && player.getPlayCardCount() >= 20 && player.getPlayCards().length >= 20) {
                this.settlementCurRound(1000);
            }
        }

        if (source.prevTask == MJ.Task.GANG) {
            if (taskId == MJ.Task.HU || taskId == MJ.Task.PENG) {
                var player = this.getPlayerByIndex(source.playerIndex);
                if (player) {
                    player.cancelLastGangForQG();
                }
            }

            if (!taskId || (taskId == MJ.Task.PASS)) {
                var curPlayer = this.getCurPlayer();
                if (curPlayer && source.playerIndex == curPlayer.getIndex()) {
                    var gangInfo = curPlayer.getLastGang();
                    if (gangInfo && this.checkGangNewCard(gangInfo)) {
                        this._curGangNewCard = 1;
                    }
                }
            }
        }
    },

    onHangupTaskNone: function(source) {
        this._super(source);

        if (source.prevTask == MJ.Task.GANG) {
            var curPlayer = this.getCurPlayer();
            if (curPlayer && source.playerIndex == curPlayer.getIndex()) {
                var gangInfo = curPlayer.getLastGang();
                if (gangInfo && this.checkGangNewCard(gangInfo)) {
                    this._curGangNewCard = 1;
                }
            }
        }
    },

    checkHuSettlement: function() {
        return true;
    },

    onSettlementHuTask: function(task) {
        var playerIndex = task.playerIndex;
        var pattern = task.pattern;
        var card = task.card;
        var from = task.from;
        var rules = task.rules;
        var huPlayer = this.getPlayerByIndex(playerIndex);

        var isZM = (playerIndex == from); // 是否是自摸

        var targetsIndex = [];
        var targets = [];
        if (isZM) {
            huPlayer.addRoundItemScores(Const.ScoreRule.ZM, Const.ItemScore[Const.ScoreRule.ZM]);
            huPlayer.setRoundScoreRule(Const.ScoreRule.ZM);
            this.enumPlayers(function(eIndex, ePlayer) {
                if (eIndex != playerIndex && !ePlayer.isRoundHu()) {
                    targetsIndex.push(eIndex);
                    targets.push(ePlayer);
                }
            });
        } else {
            var dpPlayer = this.getPlayerByIndex(from);
            if (!dpPlayer.existRoundScoreRule(Const.ScoreRule.DH)) { // 先判断是否有点炮加番，避免一炮多响重复
                dpPlayer.addRoundItemScores(Const.ScoreRule.DH, Const.ItemScore[Const.ScoreRule.DH]);
                dpPlayer.setRoundScoreRule(Const.ScoreRule.DH);
            }

            targetsIndex.push(from);
            targets.push(dpPlayer);
        }

        var patternScore = Const.PatternScore[pattern];

        for (var i = 0; i < rules.length; ++i) {
            var rule = rules[i];
            switch (rule) {
                case Const.ScoreRule.QG:
                    if (!isZM) {
                        var targetPlayer = targets[0];
                        if (!targetPlayer.existRoundScoreRule(rule)) {
                            targetPlayer.setRoundScoreRule(rule);
                            //targetPlayer.cancelLastGangForQG(card);
                        }
                    }
                    break;
                case Const.ScoreRule.GSP:
                    if (!isZM) {
                        var targetPlayer = targets[0];
                        if (!targetPlayer.existRoundScoreRule(rule)) {
                            targetPlayer.setRoundScoreRule(rule);
                            targetPlayer.addRoundItemScores(rule, Const.ItemScore[rule] + Const.ItemScore[Const.ScoreRule.DH]);
                            //targetPlayer.setLastGangUnscored();
                        }
                        targetPlayer.unsetRoundItemScore(Const.ScoreRule.DH);
                        targetPlayer.unsetRoundScoreRule(Const.ScoreRule.DH);
                    }
                    break;
                case Const.ScoreRule.GSH:
                    if (isZM) {
                        huPlayer.setRoundScoreRule(rule);
                        huPlayer.addRoundItemScores(rule, Const.ItemScore[rule] + Const.ItemScore[Const.ScoreRule.ZM]);
                        huPlayer.unsetRoundItemScore(Const.ScoreRule.ZM);
                        huPlayer.unsetRoundScoreRule(Const.ScoreRule.ZM);
                    }
                    break;
                default:
                    huPlayer.setRoundScoreRule(rule);
                    huPlayer.addRoundItemScores(rule, Const.ItemScore[rule]);
                    break;
            }
        }

        var huResult = isZM ? MJ.Result.ZM : MJ.Result.DH;
        huPlayer.setRoundResult(huResult, targetsIndex, card);
        huPlayer.setRoundPattern(pattern, patternScore);

        this.broadcast("onPlayerHu", {
            playerIndex: playerIndex,
            card: card,
            from: from,
        });
    },

    onSettlement: function() {
        this.enumPlayers(function(eIndex, ePlayer) {
            this._settlementPlayerTing(ePlayer);
        }.bind(this));

        this.enumPlayers(function(eIndex, ePlayer) {
            ePlayer.settlementRules();
        }.bind(this));

        this._settlementRules();

        this.enumPlayers(function(eIndex, ePlayer) {
            ePlayer.settlementGangScore();
            ePlayer.settlementPatternScore();
        }.bind(this));

        // 计算新的庄家
        if (this.isRoundHZ() || this.getFirstHuPlayerIndex() == this._dealerIndex) {
            this._dealerLZ++;
        } else {
            this._dealerIndex = this.getNextIndex(this._dealerIndex);
            this._dealerLZ = 1;

            if (this._dealerIndex == 1) {
                this._curTurns++; // 重新切换回东风位时圈数+1
            }
        }
    },

    onCurRoundFinished: function() {
        this._super();

        this.broadcast("onDealerChanged", {
            dealer: this._dealerIndex,
            dealerLZ: this._dealerLZ,
            curTurns: this._curTurns
        });
    },

    /******************************************************************
     * 消息处理
     ******************************************************************/

    handleSelectPiao: function(player, msg, callback) {
        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING}); return;
        }

        if (!this.getOption("PIAO")) {
            callback({code: SubCode.PIAO_NOT_ALLOWED}); return;
        }

        if (player.isPiaoSelected()) {
            callback({code: SubCode.PIAO_STATUS_ERROR}); return;
        }

        var isPiao = msg.piao ? true : false;
        player.setPiao(isPiao);

        callback({});

        this.broadcast("onPlayerSelectPiao", {
            playerIndex: player.getIndex(),
            piao: msg.piao
        });

        var isAllSelected = true;
        var results = {};
        this.enumPlayers(function(eIndex, ePlayer) {
            results[eIndex] = ePlayer.isPiao();
            if (!ePlayer.isPiaoSelected()) {
                isAllSelected = false;
            }
        });

        if (isAllSelected) {
            var msg = {"players": results};
            this.enumPlayers(function(eIndex, ePlayer) {
                ePlayer.send("onPlayerPiaoSelected", msg);
            }.bind(this));

            this._piaoStatus = Const.PiaoStatus.FINISHED;
            this.preStartPlay();
        }
    },

    /******************************************************************
     * 功能接口
     ******************************************************************/

    /**
     * 结算玩家是否听牌
     * @param player
     * @private
     */
    _settlementPlayerTing: function(player) {
        //已听牌玩家不用再检测
        if (player.isRoundTing()) {
            return;
        }

        // 对未胡牌的玩家检查是否听牌
        var tings = player.checkTing();
        var pattern = Const.Pattern.NONE;
        var patternScore = 0;
        for (var i = 0; i < tings.length; ++i) {
            var ting = tings[i];
            var score = Const.PatternScore[ting.pattern];
            if (score > patternScore) {
                pattern = ting.pattern;
                patternScore = score;
            }
        }

        player.setRoundPattern(pattern, 0);
    },

    _settlementRules: function() {
        if (this.isRoundHZ()) {
            return;
        }

        // 判断 三家清/四家清
        var siJiaQingCount = 0;
        var sanJiaQingCount = 0;
        this.enumPlayers(function(eIndex, ePlayer) {
            if (ePlayer._stat.roundRules[Const.ScoreRule.MenQing]) {
                siJiaQingCount++;
                if (!ePlayer.isRoundHu()) {
                    sanJiaQingCount++;
                }
            }
        });

        if (siJiaQingCount == 4) {
            this.enumPlayers(function(eIndex, ePlayer) {
                delete ePlayer._stat.roundRules[Const.ScoreRule.MenQing];
                if (ePlayer.isRoundHu()) {
                    ePlayer._stat.roundRules[Const.ScoreRule.SiJiaQing] = 1;
                }
            }.bind(this));
        } else if (sanJiaQingCount == 3) {
            this.enumPlayers(function(eIndex, ePlayer) {
                delete ePlayer._stat.roundRules[Const.ScoreRule.MenQing];
                if (ePlayer.isRoundHu()) {
                    ePlayer._stat.roundRules[Const.ScoreRule.SanJiaQing] = 1;
                }
            }.bind(this));
        }

        this.enumPlayers(function(eIndex, ePlayer) {
            if (ePlayer.isDealer()) {
                ePlayer.addRoundItemScores(Const.ScoreReason.LZ, Const.ItemScore[Const.ScoreRule.LZ]);
            }

            if (ePlayer.isBaoTing()) {
                ePlayer.addRoundItemScores(Const.ScoreReason.BT, Const.ItemScore[Const.ScoreRule.BT]);
            }

            ExObject.each(ePlayer._stat.roundRules, function(rule, value) {
                ePlayer.addRoundItemScores(rule, Const.ItemScore[rule] * value);
                ePlayer.setRoundScoreRule(rule);
            });
        }.bind(this));
    },
});